#include "tools/klib.h"
#include "tools/log.h"
#include "comm/cpu_instr.h"

void kernel_strcpy (char * dest, const char * src) {
    if (!src) {
        return;
    }

    while ( *src) {
        *dest++ = *src++;
    }
    *dest = '\0';
}

void kernel_strncpy(char * dest, const char * src, int size) {
    if (!dest || !src || !size) {
        return;
    }

    char * d = dest;
    const char * s = src;

    while ((size-- > 0) && (*s)) {
        *d++ = *s++;
    }
    if (size == 0) {
        *(d - 1) = '\0';
    } else {
        *d = '\0';
    }
}

int kernel_strlen(const char * str) {
    if (str == (const char *)0) {
        return 0;
    }

	const char * c = str;

	int len = 0;
	while (*c++) {
		len++;
	}

	return len;
}

/**
 * 比较两个字符串，最多比较size个字符
 * 如果某一字符串提前比较完成，也算相同
 */
int kernel_strncmp (const char * s1, const char * s2, int size) {
    if (!s1 || !s2) {
        return -1;
    }

    while (*s1 && *s2 && (*s1 == *s2) && size) {
    	s1++;
    	s2++;
    }

    return !((*s1 == '\0') || (*s2 == '\0') || (*s1 == *s2));
}

void kernel_memcpy (void * dest, void * src, int size) {
    if (!dest || !src || !size) {
        return;
    }

    uint8_t * s = (uint8_t *)src;
    uint8_t * d = (uint8_t *)dest;
    while (size--) {
        *d++ = *s++;
    }
}

void kernel_memset(void * dest, uint8_t v, int size) {
    if (!dest || !size) {
        return;
    }

    uint8_t * d = (uint8_t *)dest;
    while (size--) {
        *d++ = v;
    }
}

int kernel_memcmp (void * d1, void * d2, int size) {
    if (!d1 || !d2) {
        return 1;
    }

	uint8_t * p_d1 = (uint8_t *)d1;
	uint8_t * p_d2 = (uint8_t *)d2;
	while (size--) {
		if (*p_d1++ != *p_d2++) {
			return 1;
		}
	}

	return 0;
}

void kernel_itoa(char * buf, unsigned int num, int base) {
    if(!num){
        //0的时候
        *buf='0';
        return;
    }

    //int to asci 
    if(base !=10 &&base !=2 && base != 16 && base != 4 ){
        *buf='\0';
        return;
    }

    if(num < 0){
        *buf++='-';
        num *=-1;
    }

    char *dest=buf;
    while(num){
        int yushu=num%base;
        char ch='\0';
        if(yushu < 10){
            ch='0'+yushu;
        }else {
            yushu-=10;
            ch='A'+yushu;
        }
        *dest++ = ch;
        num/=base;
    }
    *dest--='\0';

    //把逆序交换成正序
    while(buf < dest){
        char temp=*buf;
        *buf=*dest;
        *dest=temp;
        dest--; buf++;
    }
    return ;

}

void kernel_sprintf(char * buffer, const char * fmt, ...){

};

void kernel_vsprintf(char * buffer, const char * fmt, va_list args) {
    //状态机  normal正常写入，read_fmt将args的值写入
    enum {NORMAL,READ_FMT} state=NORMAL;

    //字符串格式化到缓冲区里
    char  *curr=buffer;
    char ch='\0';
    while((ch=*fmt++)){

        switch (state)
        {
        case NORMAL:
            if(ch=='%'){
                state=READ_FMT;
            }else{
                *curr++=ch;
            }
            break;
        case READ_FMT:
            if(ch=='s'){
                //将另一个字符串写入
                const char *var=va_arg(args,char *);
                while((ch=*var++)){
                    *curr++=ch;
                }
            }else if(ch=='d'){
                //十进制
                int num=va_arg(args,int);
                char buffer[128];
                kernel_itoa(buffer,num,10);
                char  *p_buffer=buffer;
                while((ch=*p_buffer++)){
                    *curr++=ch;
                }       
            }else if(ch=='x'){
                //16进制
                int num=va_arg(args,int);
                char buffer[128];
                kernel_itoa(buffer,num,16);
                char  *p_buffer=buffer;
                while((ch=*p_buffer++)){
                    *curr++=ch;
                }   
                
            }else if(ch=='c'){
                //字符，要用int  char 会出错
                char var=va_arg(args,int);
                *curr++=var;
            }
            state=NORMAL;
            break;
        default:
            break;
        }
        
    }
}

void panic(const char *file,int line,const char *func,const char *cond){
    log_printf("assert fails");
    log_printf("file_name : %s line : %d  func %s",file,line,func);
    log_printf("funcion : %s",cond);
    for(;;){
        hlt();
    }
};

char * get_file_name (const char * name){
    //获取文件名  /home/aaa/project/a.txt  返回a.txt
    char *current_pointer=name;
    while(*current_pointer!='\0'){
        current_pointer++;
    }

    while(*current_pointer != '\\' && *current_pointer != '/' && current_pointer!=name){
        current_pointer--;
    }
    return current_pointer+1;

};
int strings_count (char * const *start) {
    int count = 0;

    if (start) {
        while (*start++) {
            count++;
        }
    }
    return count;
}